#include "StdAfx.h"
#include "FEngineType.h"
#include "KeyboardInputListener.h"
#include "MouseInputListener.h"
#include "FEApplication.h"
#include "Node.h"
#include "Camera.h"
#include "FreeCameraHandler.h"

namespace FEngine
{
	FreeCameraHandler::FreeCameraHandler(Camera* _cam, const Vector3& _pos, const Vector3& _lookDir)
		: Node(), MouseInputListener(), mCamera(_cam)
	{
		mRotY = new Node();
		mRotY->setPosition(_pos);
		mRotX = new Node();
		mRotY->addChild(mRotX);

		mLookAtPos = new Node();
		mLookAtPos->setPosition(_lookDir.x, 0, _lookDir.z);
		mRotX->addChild(mLookAtPos);

		mCamera->setPosition(mRotY->getPositionWorld());
		mCamera->lookAt(mLookAtPos->getPositionWorld());
		
		mMouseMovement	= Vector2(0, 0);
		mRotationX		= 0;
		mRotationY		= 0;
		mMoveSpeed		= 20;
		mRotationSpeedX = 0.1f;
		mRotationSpeedY = 0.1f;

		InputManager::getInstance()->registerMouseInputListener(this);
	}

	FreeCameraHandler::~FreeCameraHandler()
	{
		InputManager::getInstance()->unregisterMouseInputListener(this);
		delete mRotY;
		delete mRotX;
		delete mLookAtPos;
	}
	
	void FreeCameraHandler::setMovementSpeed(int _speed)
	{
		mMoveSpeed = _speed;
	}
	
	void FreeCameraHandler::update(double _elapsedTime)
	{
		// Move speed boost
		int moveSpeed = mMoveSpeed;
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_SHIFT))
			moveSpeed *= 4;

		// Position
		Vector3 moveDir = Vector3(0, 0, 0);
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_Z))
			moveDir.z += moveSpeed * (float)_elapsedTime / 1000;
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_S))
			moveDir.z -= moveSpeed * (float)_elapsedTime / 1000;
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_D))
			moveDir.x += moveSpeed * (float)_elapsedTime / 1000;
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_Q))
			moveDir.x -= moveSpeed * (float)_elapsedTime / 1000;

		// Rotation
		Vector2 rotDir = Vector2(mMouseMovement.x, mMouseMovement.y);
		if (rotDir.y != 0)
		{
			mRotationX += rotDir.y * mRotationSpeedY;
			if (mRotationX < -75)
				mRotationX = -75;
			if (mRotationX > 75)
				mRotationX = 75;
			mRotX->setRotation((float)DEGREES_TO_RADIANS(mRotationX), 0, 0);
			mMouseMovement.y = 0;
		}
		if (rotDir.x != 0)
		{
			mRotationY += rotDir.x * mRotationSpeedX;
			mRotY->setRotation(0, 0, (float)DEGREES_TO_RADIANS(mRotationY));
			mMouseMovement.x = 0;
		}

		// Position Y
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_E))
			moveDir.y += mMoveSpeed * (float)_elapsedTime / 1000;
		if (InputManager::getInstance()->isKeyDown(InputManager::KEY_A))
			moveDir.y -= mMoveSpeed * (float)_elapsedTime / 1000;

		// Apply the new position and rotation
		if (moveDir != Vector3(0, 0, 0) || rotDir != Vector2(0, 0))
		{
			Matrix4 cameraWorldMatrix;
			Matrix4 viewMatrix;
			
			D3DXMatrixLookAtLH(&viewMatrix, &mRotY->getPositionWorld(), &mLookAtPos->getPositionWorld(), &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
			D3DXMatrixInverse(&cameraWorldMatrix, NULL, &viewMatrix);
			cameraWorldMatrix._41 = cameraWorldMatrix._42 = cameraWorldMatrix._43 = 0;

			D3DXVec3TransformCoord(&moveDir, &moveDir, &cameraWorldMatrix);
			
			mRotY->translate(moveDir);

			mCamera->setPosition(mRotY->getPositionWorld());
			mCamera->lookAt(mLookAtPos->getPositionWorld());
		}
	}

	void FreeCameraHandler::mouseButtonPressed(int _button, const Vector2& _position)
	{
	}

	void FreeCameraHandler::mouseButtonReleased(int _button, const Vector2& _position)
	{
	}

	void FreeCameraHandler::mouseMoved(const Vector2& _delta)
	{
		if (InputManager::getInstance()->isMouseButtonDown(InputManager::MS_LEFTBUTTON))
			mMouseMovement += _delta;
	}

} // namespace FEngine
